// 汉中库得网络科技版权所有
#include "Db.h"

#include "Record.h"

DEFINE_LOG_CATEGORY(LogSQLiteDbKit);

bool UDb::Save(const FString TableName, URecord* Record){
	if(!bIsOpened){
		Open();
	}
	FString Sql = "INSERT INTO `" + TableName + "`(";
	for(auto Temp : Record->GetMap()){
		Sql.Append("`" + Temp.Key + "`").Append(", ");
	}
	Sql = Sql.Left(Sql.Len() - 2) + ")" + " VALUES(";
	for(auto Temp : Record->GetMap()){
		Sql.Append("'" + Temp.Value + "'").Append(", ");
	}
	Sql = Sql.Left(Sql.Len() - 2) + ")";
	UE_LOG(LogSQLiteDbKit, Log, TEXT("SQL: %s"), *Sql)

	const bool Result = ExecSql(Sql);
	Close();
	return Result;
}

URecord* UDb::FindById(const FString& TableName, const FString& Id){
	return FindById(TableName, "id", Id);
}

URecord* UDb::FindById(const FString& TableName, const FString& IdColumnName, const FString& Id){
	if(!bIsOpened){
		Open();
	}
	FString Sql = "SELECT * FROM `" + TableName + "` WHERE `" + IdColumnName + "`='" + Id + "'";
	UE_LOG(LogSQLiteDbKit, Log, TEXT("SQL: %s"), *Sql)

	URecord* Record = nullptr;
	FDataBaseRecordSet* ResultSet;
	if(ExecSql(Sql, ResultSet)){
		if(ResultSet->GetRecordCount() != 0){
			Record = NewObject<URecord>();
			FDataBaseRecordSet::TIterator Row(ResultSet);
			while (Row){
				for(auto Column: ResultSet->GetColumnNames()){
					Record->Set(Column.ColumnName, Row->GetString(*(Column.ColumnName)));
				}
				++Row;
			}
		}
	}
	// 此处必须删除，否则关闭数据库连接时会失败
	delete ResultSet;
	ResultSet = nullptr;
	Close();
	return Record;
}

bool UDb::Update(const FString TableName, const FString& IdColumnName, URecord* Record){
	if(!bIsOpened){
		Open();
	}
	FString IdKey, IdValue;
	FString Sql = "UPDATE `" + TableName + "` SET ";
	for(auto Temp : Record->GetMap()){
		if(Temp.Key != IdColumnName){
			Sql.Append("`" + Temp.Key + "`='" + Temp.Value + "',");
		}else{
			IdKey = Temp.Key;
			IdValue = Temp.Value;
		}
	}
	Sql = Sql.Left(Sql.Len() - 1);
	Sql.Append(" WHERE `" + IdKey + "`='" + IdValue + "'");
	UE_LOG(LogSQLiteDbKit, Log, TEXT("SQL: %s"), *Sql)
	const bool Result = ExecSql(Sql);

	Close();
	return Result;
}

int32 UDb::QueryInt(FString Sql){
	if(!bIsOpened){
		Open();
	}
	int32 Result = 0;
	FDataBaseRecordSet* ResultSet;
	if(ExecSql(Sql, ResultSet)){
		if(ResultSet->GetRecordCount() != 0){
			FDataBaseRecordSet::TIterator Row(ResultSet);
			while (Row){
				for(auto Column : Row->GetColumnNames()){
					Result = Row->GetInt(*(Column.ColumnName));
				}
				++Row;
			}
		}
	}
	delete ResultSet;
	ResultSet = nullptr;
	Close();
	return Result;
}

void UDb::Open(){
	if(DBFile != ""){
		FString File = FPaths::ProjectDir() + TEXT("Content/") + DBFile;
		if(FPaths::FileExists(File)){
			if(DBConnection.Open(*FPaths::ConvertRelativePathToFull(File), nullptr, nullptr)){
				bIsOpened = true;
			}else{
				bIsOpened = false;
			}
		}else{
			UE_LOG(LogSQLiteDbKit, Warning, TEXT("File Not Found: %s"), *File)	
		}
	}else{
		UE_LOG(LogSQLiteDbKit, Warning, TEXT("SQLiteDbKit未配置，请使用UDb::Config(FString DBFileName)来配置SQLite数据库文件"))
	}
}

void UDb::Close(){
	if(bIsOpened){
		DBConnection.Close();
		bIsOpened = false;
	}
}

bool UDb::ExecSql(const FString& Sql){
	bool result = false;
	if(bIsOpened){
		result = DBConnection.Execute(*Sql);
	}
	return result;
}

bool UDb::ExecSql(const FString& Sql, FDataBaseRecordSet*& ResultSet){
	bool result = false;
	if(bIsOpened){
		result = DBConnection.Execute(*Sql, ResultSet);
	}
	return result;
}

void UDb::Config(FString file){
	if(FPaths::FileExists(file)){
		DBFile = file;
	}else{
		UE_LOG(LogSQLiteDbKit, Warning, TEXT("File %s is not found!"), *file)
	}
}